#include "BinaryQueue.h"

#include <iostream>

BinaryQueue::BinaryQueue()
{
	for (int32_t i = 0; i < MAX_MESSAGE_COUNT; i++)
	{
		allMsg[i] = new Message;
		idleQueue[i] = allMsg[i];
	}

	idleCount = MAX_MESSAGE_COUNT;
	busyCount = 0;
}

BinaryQueue::~BinaryQueue()
{
	for (auto msg : allMsg)
	{
		delete msg;
	}
}

void BinaryQueue::enqueueIdle(Message* msg)
{
	std::unique_lock<std::mutex> lock(guardIdle);

	if (msg != nullptr)
	{
		msg->msg = "";
		msg->quit = false;
	}
	this->idleQueue[idleCount] = msg;
	++idleCount;

	std::cout << "Idle Count: " << this->idleCount << std::endl;

	signalIdle.notify_one();
}

Message* BinaryQueue::dequeueIdle()
{
	std::unique_lock<std::mutex> lock(guardIdle);
	while (this->idleCount == 0)
	{
		signalIdle.wait(lock, [this]() { return this->idleCount != 0; });
	}

	--this->idleCount;
	std::cout << "Idle Count: " << this->idleCount << std::endl;
	
	return this->idleQueue[idleCount];
}

void BinaryQueue::enqueueBusy(Message* msg)
{
	std::unique_lock<std::mutex> lock(guardUsing);

	this->busyQueue[busyCount] = msg;
	++busyCount;
	std::cout << "Busy Count: " << this->busyCount << std::endl;

	signalUsing.notify_one();
}

Message* BinaryQueue::dequeueBusy()
{
	std::unique_lock<std::mutex> lock(guardUsing);
	while (this->busyCount == 0)
	{
		signalUsing.wait(lock, [this]() { return this->busyCount != 0; });
	}

	auto msg = this->busyQueue[0];

	for (int32_t i = 1; i < this->busyCount; i++)
	{
		this->busyQueue[i - 1] = this->busyQueue[i];
	}
	--this->busyCount;
	std::cout << "Busy Count: " << this->busyCount << std::endl;

	return msg;
}
